#route.py
# Organized imports

# 标准库
import logging
import traceback

# 第三方库
from flask import render_template, redirect, url_for, request, flash, current_app, jsonify
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SelectMultipleField, SelectField
from wtforms.fields import DateField
from wtforms.validators import DataRequired, Optional
from werkzeug.datastructures import MultiDict

# 本地模块
from inc import logger
from . import jira_bp
from .attachment_routes import attachment_bp
from ..utils import member_login_required, get_current_member
from .services import (
    get_jira_projects,
    create_jira_project,
    get_project_detail,
    delete_project,
    update_jira_project,
    create_test_project,
    submit_test_approval,
    approve_step,
    get_project_status
)
from ..approval.services import get_approval_history # 导入审批历史服务
from ..workflow.services import ProjectWorkflow
from inc.models import AdminMember, db, JiraProject, JiraCategory, JiraLevel, JiraApprovalFlow, JiraStage, JiraReview
# 注册蓝图
jira_bp.register_blueprint(attachment_bp, url_prefix='/attachments')

# 将表单定义移到顶层，以便复用
class ProjectForm(FlaskForm):
    """项目表单"""
    name = StringField('项目名称', validators=[DataRequired()])
    description = TextAreaField('项目描述')
    start_date = DateField('开始日期', format='%Y-%m-%d', validators=[Optional()])
    end_date = DateField('结束日期', format='%Y-%m-%d', validators=[Optional()])
    category_id = SelectField('项目分类', coerce=int, validators=[DataRequired()])
    level_id = SelectField('项目级别', coerce=int, validators=[DataRequired()])
    approval_flow_id = SelectField('审批流程', coerce=int, validators=[DataRequired()])
    first_approver_id = SelectField('第一审批人', coerce=int)
    member_ids = SelectMultipleField('项目成员', coerce=int)

def _get_project_form_data():
    """辅助函数，用于加载项目表单所需的通用数据"""
    members = AdminMember.query.filter_by(status=True).all()
    categories = JiraCategory.query.all()
    levels = JiraLevel.query.all()
    flows = JiraApprovalFlow.query.options(db.joinedload(JiraApprovalFlow.department)).all()
    approvers = [m for m in members if m.has_permission('REVIEW_PROJECT')]
    return {
        "members": members,
        "categories": categories,
        "levels": levels,
        "flows": flows,
        "approvers": approvers,
    }

@jira_bp.route('/')
@member_login_required
def list_projects():
    """项目列表"""
    status_filter = request.args.get('status', 'all')
    current_member = get_current_member()
    projects = get_jira_projects(current_member.id, status_filter)
    return render_template('member/jira/jira_list.html',
                           projects=projects,
                           status_filter=status_filter,
                           current_member=current_member)


@jira_bp.route('/create', methods=['GET', 'POST'])
@member_login_required
def create_project():
    """创建项目"""
    current_member = get_current_member()
    form = ProjectForm()
    context = _get_project_form_data()

    # 动态填充选项
    form.member_ids.choices = [(m.id, m.name) for m in context['members']]
    form.category_id.choices = [(c.id, c.name) for c in context['categories']]
    form.level_id.choices = [(l.id, l.name) for l in context['levels']]
    form.approval_flow_id.choices = [(f.id, f"{f.name} ({f.department.name if f.department else '通用'})") for f in context['flows']]
    form.first_approver_id.choices = [(a.id, a.name) for a in context['approvers']]

    if form.validate_on_submit():
        try:
            form_data = form.data
            # 确保项目负责人被包含在成员中
            if current_member.id not in form_data['member_ids']:
                form_data['member_ids'].append(current_member.id)

            project = create_jira_project(current_member.id, form_data)
            # 状态在 service 层处理，这里不再手动设置
            flash('项目已成功创建为草稿', 'success')
            return redirect(url_for('member.jira.project_detail', project_id=project.id))
        except Exception as e:
            db.session.rollback()
            flash(f'创建项目失败: {str(e)}', 'danger')
            logging.error(f"Create project error: {str(e)}\n{traceback.format_exc()}")

    return render_template('member/jira/jira_create.html', form=form, **context)


@jira_bp.route('/<int:project_id>/edit', methods=['GET', 'POST'])
@member_login_required
def edit_project(project_id):
    """编辑项目"""
    current_member = get_current_member()
    project = JiraProject.query.get_or_404(project_id)

    if project.owner_id != current_member.id:
        flash('只有项目负责人可以编辑项目', 'danger')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))

    if project.status not in [JiraProject.DRAFT, JiraProject.REJECTED]:
        flash('只有草稿或被拒绝状态的项目可以编辑', 'danger')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))

    form = ProjectForm(obj=project)
    context = _get_project_form_data()

    # 动态填充选项
    form.member_ids.choices = [(m.id, m.name) for m in context['members']]
    form.category_id.choices = [(c.id, c.name) for c in context['categories']]
    form.level_id.choices = [(l.id, l.name) for l in context['levels']]
    form.approval_flow_id.choices = [(f.id, f"{f.name} ({f.department.name if f.department else '通用'})") for f in context['flows']]
    form.first_approver_id.choices = [(a.id, a.name) for a in context['approvers']]

    if form.validate_on_submit():
        try:
            form_data = form.data
            # 确保项目负责人被包含在成员中
            if current_member.id not in form_data['member_ids']:
                form_data['member_ids'].append(current_member.id)

            update_jira_project(project_id, current_member.id, form_data)
            flash('项目更新成功', 'success')
            return redirect(url_for('member.jira.project_detail', project_id=project_id))
        except Exception as e:
            db.session.rollback()
            flash(f'更新项目失败: {str(e)}', 'danger')
            logging.error(f"Update project error: {str(e)}\n{traceback.format_exc()}")

    # GET 请求时，填充已选成员
    if request.method == 'GET':
        form.member_ids.data = [m.member_id for m in project.members]

    return render_template('member/jira/jira_edit.html',
                         form=form,
                         project=project,
                         current_member=get_current_member(),
                         **context)



@jira_bp.route('/<int:project_id>')
@member_login_required
def project_detail(project_id):
    """项目详情"""
    current_member = get_current_member()
    project = get_project_detail(project_id, current_member.id)
    approval_history_raw = get_approval_history(project_id)

    # 为审批历史添加 status_label
    status_labels = {
        'pending': '待处理',
        'approved': '已批准',
        'rejected': '已驳回'
    }
    approval_history = []
    for record in approval_history_raw:
        record['status_label'] = status_labels.get(record['status'], '未知状态')
        approval_history.append(record)


    # 计算当前用户是否对该项目有待审批记录
    pending_approval_id = None
    try:
        pending = db.session.query(JiraReview).filter(
            JiraReview.project_id == project_id,
            JiraReview.reviewer_id == current_member.id,
            JiraReview.status == 'pending'
        ).order_by(JiraReview.created_at.asc()).first()
        if pending:
            pending_approval_id = pending.id
    except Exception:
        pending_approval_id = None

    # 进度计算已经在服务层完成，直接使用project对象中的进度数据
    return render_template('member/jira/jira_detail.html',
                         project=project,
                         approval_history=approval_history,
                         current_member=current_member,
                         pending_approval_id=pending_approval_id)




@jira_bp.route('/<int:project_id>/submit', methods=['POST'])
@member_login_required
def submit_project(project_id):
    """提交项目审核"""
    current_member = get_current_member()
    try:
        ProjectWorkflow.submit_for_review(project_id, current_member.id)
        flash('项目已提交审核', 'success')
    except Exception as e:
        flash(f'提交审核失败: {str(e)}', 'danger')
        logger.error(f"Submit project for review error: {str(e)}\n{traceback.format_exc()}")
    return redirect(url_for('member.jira.project_detail', project_id=project_id))


@jira_bp.route('/<int:project_id>/start', methods=['POST'])
@member_login_required
def start_project(project_id):
    """开始项目"""
    current_member = get_current_member()
    try:
        ProjectWorkflow.start_project(project_id, current_member.id)
        flash('项目已开始', 'success')
    except Exception as e:
        flash(f'开始项目失败: {str(e)}', 'danger')
        logger.error(f"Start project error: {str(e)}\n{traceback.format_exc()}")
    return redirect(url_for('member.jira.project_detail', project_id=project_id))


@jira_bp.route('/<int:project_id>/request-closure', methods=['POST'])
@member_login_required
def request_project_closure(project_id):
    """请求项目结项"""
    current_member = get_current_member()
    try:
        project = ProjectWorkflow.request_project_closure(project_id, current_member.id)
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return jsonify({'status': 'success', 'message': '项目结项申请已提交'})
        flash('项目结项申请已提交', 'success')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))
    except ValueError as e:
        # 业务规则验证失败不记录日志
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return jsonify({'status': 'warning', 'message': str(e)}), 400
        flash(str(e), 'warning')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))
    except Exception as e:
        # 真正的系统错误记录日志
        error_msg = f'提交结项申请失败: {str(e)}'
        logger.error(f"系统错误: {str(e)}\n{traceback.format_exc()}")
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            return jsonify({'status': 'error', 'message': error_msg}), 400
        flash(error_msg, 'danger')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))



@jira_bp.route('/<int:project_id>/approve-closure', methods=['POST'])
@member_login_required

def approve_project_closure(project_id):
    """批准项目结项"""
    current_member = get_current_member()
    try:
        notes = request.form.get('notes', '')
        score = float(request.form.get('score', 0))
        project = ProjectWorkflow.approve_project_closure(project_id, current_member.id, notes, score)
        flash('项目结项已批准', 'success')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))
    except Exception as e:
        flash(f'批准结项失败: {str(e)}', 'danger')
        logger.error(f"Approve project closure error: {str(e)}\n{traceback.format_exc()}")
        return redirect(url_for('member.jira.project_detail', project_id=project_id))

@jira_bp.route('/<int:project_id>/reject-closure', methods=['POST'])
@member_login_required
def reject_project_closure(project_id):
    """拒绝项目结项"""
    current_member = get_current_member()
    try:
        notes = request.form.get('notes', '')
        project = ProjectWorkflow.reject_project_closure(project_id, current_member.id, notes)

        # 将项目状态重置为进行中，允许再次提交结项
        project.status = JiraProject.IN_PROGRESS
        db.session.commit()

        flash('项目结项申请已拒绝，项目状态已重置为进行中', 'success')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))
    except Exception as e:
        db.session.rollback()
        flash(f'拒绝结项失败: {str(e)}', 'danger')
        logger.error(f"Reject project closure error: {str(e)}\n{traceback.format_exc()}")
        return redirect(url_for('member.jira.project_detail', project_id=project_id))

@jira_bp.route('/<int:project_id>/closure-reviews', methods=['GET'])
@member_login_required
def get_closure_reviews(project_id):
    """获取项目结项审批记录"""
    try:
        reviews = JiraReview.query.filter_by(
            project_id=project_id,
            is_closure_review=True
        ).all()

        review_list = []
        for review in reviews:
            review_list.append({
                "id": review.id,
                "status": review.status,
                "notes": review.notes,
                "review_notes": review.review_notes,
                "created_at": review.created_at.isoformat() if review.created_at else None,
                "reviewed_at": review.reviewed_at.isoformat() if review.reviewed_at else None,
                "reviewer": review.reviewer.name if review.reviewer else None,
                "submitter": review.submitter.name if review.submitter else None
            })

        return jsonify(review_list)
    except Exception as e:
        flash(f'获取结项审批记录失败: {str(e)}', 'danger')
        logger.error(f"Get closure reviews error: {str(e)}\n{traceback.format_exc()}")
        return redirect(url_for('member.jira.project_detail', project_id=project_id))

@jira_bp.route('/<int:project_id>/complete', methods=['POST'])
@member_login_required
def complete_project(project_id):
    """完成项目（已废弃，保留以兼容旧代码）"""
    current_member = get_current_member()
    try:
        flash('此方法已废弃，请使用request_project_closure方法', 'warning')
        return redirect(url_for('member.jira.project_detail', project_id=project_id))
    except Exception as e:
        flash(f'操作失败: {str(e)}', 'danger')
        logger.error(f"Complete project error: {str(e)}\n{traceback.format_exc()}")
        return redirect(url_for('member.jira.project_detail', project_id=project_id))


@jira_bp.route('/<int:project_id>/delete', methods=['POST'])
@member_login_required
def delete_project_route(project_id):
    """删除项目"""
    current_member = get_current_member()
    try:
        delete_project(project_id, current_member.id)
        flash('项目已删除', 'success')
        return redirect(url_for('member.jira.list_projects'))
    except Exception as e:
        flash(f'删除项目失败: {str(e)}', 'danger')
        logger.error(f"Delete project error: {str(e)}\n{traceback.format_exc()}")
        return redirect(url_for('member.jira.project_detail', project_id=project_id))

# 附件下载路由
@jira_bp.route('/attachments/download/<int:attachment_id>')
@member_login_required
def download_attachment(attachment_id):
    from flask import send_from_directory
    from inc.models import ProjectAttachment
    import os

    attachment = ProjectAttachment.query.get_or_404(attachment_id)
    current_member = get_current_member()

    # 检查权限
    if current_member.id not in [m.member_id for m in attachment.project.members] and current_member.id != attachment.project.owner_id:
        return "无权访问", 403

    directory = os.path.dirname(attachment.filepath)
    filename = os.path.basename(attachment.filepath)
    return send_from_directory(directory, filename, as_attachment=True)


